package com.fusion.core.comm.rpc;

import com.fusion.Version;
import com.fusion.core.CoreSubsystem;
import com.fusion.core.T;
import com.fusion.core.comm.Connection;
import com.fusion.core.comm.Packet;
import com.fusion.core.comm.RPC;
import com.fusion.core.file.hash.Hash;
import com.fusion.core.node.Friend;

import java.io.IOException;

/**
 *
 * Sent as a reply to a GetUserList
 *
 * Recived when we connect to a new user, after we've sent GetUserList
 *
 * @author SwethaShivakumar 
 * Project: fusion
 * Date: Mar 6, 2009
 * URL: http://fusionwiki.co.cc
 * Mail Me At: shiva@fusionproject.co.cc
 */
public class UserInfoV2 extends RPC {
    public UserInfoV2() {
    }

    public void execute(Packet in) throws IOException {
        Friend f = con.getRemoteFriend();

        boolean guidMismatch = false;
        int remoteGUID = in.readInt();
        if (remoteGUID != f.getGuid()) {
            if(T.t)T.warn("GUID mismatch!!! Closing connection.");
//            f.setGuid(remoteGUID);
            guidMismatch = true;
        }

        int port = in.readInt();
        f.updateLastKnownHostInfo(manager.getNetMan().getSocketFor(con).getInetAddress().getHostAddress(), port);
        f.setShareSize(in.readLong());
        int buildNumber = in.readInt();
        f.setFusionBuildNumber(buildNumber);
        f.setTotalBytesReceived(in.readLong());
        f.setTotalBytesSent(in.readLong());
        f.setHighestIncomingCPS(in.readInt());
        f.setHighestOutgoingCPS(in.readInt());
        f.setNumberOfFilesShared(in.readInt());
        f.setNumberOfInvitedFriends(in.readInt());

        if (CoreSubsystem.ALLOW_TO_SEND_UPGRADE_TO_FRIENDS) {
            if (buildNumber < Version.BUILD_NUMBER) {
                //remote has old version
                Hash h = core.getFileManager().getAutomaticUpgrade().getMyJarHash();
                if (h != null) send(new NewVersionAvailable(h));
            }
        }

        //now that we have a good connection to friend: verify that we only have ONE connection
        if (con.getRemoteFriend().hasMultipleFriendConnections()) {
            if(T.t)T.trace("Has multple connections to a friend. Figuring out wich one of us should close the connection");
            if ((con.getDirection() == Connection.Direction.IN && con.getRemoteUserGUID() > manager.getMyGUID()) ||
                    (con.getDirection() == Connection.Direction.OUT && manager.getMyGUID() > con.getRemoteUserGUID())) {
                //serveral connections. Its up to us to close one
                if(T.t)T.info("Already connected to "+con.getRemoteFriend()+". Closing connection");
                send(new GracefulClose(GracefulClose.DUPLICATE_CONNECTION));
                //con.close();
                //close connection when we in turn receive a graceful close
            }
        }
        if (guidMismatch) {
            send(new GracefulClose(GracefulClose.GUID_MISMATCH));
        } else {
            //this is the place for an event: "FriendSuccessfullyConnected".
            core.getNetworkManager().signalFriendConnected(con.getRemoteFriend());
            core.getUICallback().nodeOrSubnodesUpdated(con.getRemoteFriend());
            core.updateLastSeenOnlineFor(con.getRemoteFriend());
            System.setProperty("fusion.network.friendsonline",""+manager.getNFriendsConnected());
        }
    }

    public Packet serializeTo(Packet p) {
        p.writeInt(manager.getMyGUID());
        p.writeInt(core.getSettings().getServer().getPort());
        p.writeLong(core.getFileManager().getTotalBytesShared());
        p.writeInt(Version.BUILD_NUMBER);

        p.writeLong(core.getNetworkManager().getBandwidthIn().getTotalBytes());
        p.writeLong(core.getNetworkManager().getBandwidthOut().getTotalBytes());
        p.writeInt((int)Math.round(core.getNetworkManager().getBandwidthIn().getHighestCPS()));
        p.writeInt((int)Math.round(core.getNetworkManager().getBandwidthOut().getHighestCPS()));
        p.writeInt(core.getFileManager().getFileDatabase().getNumberOfFiles());
        p.writeInt(core.getSettings().getMy().getInvitations());

        return p;
    }
}
